// entities/csp.go
package entities

import (
	"alan/exp3/src/system"
	"errors"
	"log"
	"math/big"
)

// CSP 代表云服务提供商
type CSP struct {
	ID            string
	EncryptedFile []*big.Int
	FileID        string
	params        *system.SystemParams
}

// NewCSP 创建一个新的CSP实例
func NewCSP(id string, params *system.SystemParams) *CSP {
	return &CSP{ID: id, params: params}
}

// StoreFile 存储数据所有者上传的加密文件
func (c *CSP) StoreFile(fileID string, data []*big.Int) {
	c.FileID, c.EncryptedFile = fileID, data
}

// ProofGen 核心算法：根据审计请求生成部分完整性证明 Γ_k。
// 计算 Γ_k = Σ (e_l * y_kil)，这是一个大整数求和。
func (c *CSP) ProofGen(req *system.AuditRequest) (*big.Int, error) {
	if req.FileID != c.FileID {
		return nil, errors.New("file ID mismatch")
	}
	partialProof := new(big.Int)
	for i, idx := range req.Indices {
		if idx >= len(c.EncryptedFile) {
			return nil, errors.New("index out of bounds")
		}
		term := new(big.Int).Mul(req.Weights[i], c.EncryptedFile[idx])
		partialProof.Add(partialProof, term)
	}
	log.Printf("[%s] Generated partial proof Gamma_k.", c.ID)
	return partialProof, nil
}

// AggregateProof 聚合所有部分证明 (模拟功能)。
// 在实际分布式系统中，这一步需要复杂的通信协议。
// 在我们的模拟中，它只是简单地将所有收到的部分证明相加。
func (c *CSP) AggregateProof(partialProofs []*big.Int) *big.Int {
	completeProof := new(big.Int)
	for _, p := range partialProofs {
		completeProof.Add(completeProof, p)
	}
	log.Printf("[%s] Aggregated all partial proofs to get complete proof Gamma.", c.ID)
	return completeProof
}

// VerifyProof 核心算法：验证聚合后的完整证明。
// 严格按照论文的验证方程(4) Λ1 * g^(Γ - floor*a) = Λ2 * gb^floor (mod p) 进行计算。
// 这里的计算都发生在 Z_p* 乘法群中。
func (c *CSP) VerifyProof(req *system.AuditRequest, completeProof *big.Int) bool {
	p, g, a, gb := c.params.P, c.params.G, c.params.A_val, c.params.Gb
	lambda1, lambda2 := req.Lambda1, req.Lambda2
	log.Printf("[%s] Starting verification...", c.ID)

	floorGammaA := new(big.Int).Div(completeProof, a)

	// LHS
	expLHS := new(big.Int).Sub(completeProof, new(big.Int).Mul(floorGammaA, a))
	gExpLHS := new(big.Int).Exp(g, expLHS, p)
	lhs := new(big.Int).Mul(lambda1, gExpLHS)
	lhs.Mod(lhs, p)

	// RHS
	gbExpRHS := new(big.Int).Exp(gb, floorGammaA, p)
	rhs := new(big.Int).Mul(lambda2, gbExpRHS)
	rhs.Mod(rhs, p)

	result := lhs.Cmp(rhs) == 0
	log.Printf("[%s] Verification result: %t (LHS: %s... vs RHS: %s...)", c.ID, result, lhs.String()[:10], rhs.String()[:10])
	return result
}
